﻿''' <summary>
''' Provides functionality to draw window frames to the screen buffer. This class is used internally by the Window
''' class and generally does not need to be used by inheritors.  The one exception being custom frame characters;
''' use the SetDoubleBar(), SetSingleBar(), and SetCharacters() methods to modify the style of the window frames.
''' </summary>
Public NotInheritable Class FrameRenderer

    Public Shared ReadOnly Property BottomLeft As Char
        Get
            Return _Characters(0)
        End Get
    End Property
    Public Shared ReadOnly Property BottomRight As Char
        Get
            Return _Characters(1)
        End Get
    End Property
    Public Shared ReadOnly Property Cross As Char
        Get
            Return _Characters(2)
        End Get
    End Property
    Public Shared ReadOnly Property Horizontal As Char
        Get
            Return _Characters(3)
        End Get
    End Property
    Public Shared ReadOnly Property TeeBottom As Char
        Get
            Return _Characters(4)
        End Get
    End Property
    Public Shared ReadOnly Property TeeLeft As Char
        Get
            Return _Characters(5)
        End Get
    End Property
    Public Shared ReadOnly Property TeeRight As Char
        Get
            Return _Characters(6)
        End Get
    End Property
    Public Shared ReadOnly Property TeeTop As Char
        Get
            Return _Characters(7)
        End Get
    End Property
    Public Shared ReadOnly Property TopLeft As Char
        Get
            Return _Characters(8)
        End Get
    End Property
    Public Shared ReadOnly Property TopRight As Char
        Get
            Return _Characters(9)
        End Get
    End Property
    Public Shared ReadOnly Property Vertical As Char
        Get
            Return _Characters(10)
        End Get
    End Property

    Private Shared _Cells(,) As FrameCellType
    Private Shared _Characters() As Char = "╚╝╬═╩╠╣╦╔╗║"

    Protected Sub New()
    End Sub

    Public Shared Sub DrawFrame(buffer As ConsoleScreenBuffer, ParamArray bounds() As Rectangle)
        DrawFrame(Console.ForegroundColor, Console.BackgroundColor, buffer, bounds)
    End Sub

    Public Shared Sub DrawFrame(forecolor As ConsoleColor, buffer As ConsoleScreenBuffer, ParamArray bounds() As Rectangle)
        DrawFrame(forecolor, Console.BackgroundColor, buffer, bounds)
    End Sub

    Public Shared Sub DrawFrame(forecolor As ConsoleColor, backcolor As ConsoleColor, buffer As ConsoleScreenBuffer, ParamArray bounds() As Rectangle)
        ReDim _Cells(buffer.Bounds.Width - 1, buffer.Bounds.Height - 1)
        Dim yupper = _Cells.GetUpperBound(1)
        Dim xupper = _Cells.GetUpperBound(0)
        Dim updateBuffer As New Action(Of Integer, Integer, Char)(Sub(x, y, c)
                                                                      buffer.Item(x, y) = c
                                                                      buffer.BackgroundColor(x, y) = backcolor
                                                                      buffer.ForegroundColor(x, y) = forecolor
                                                                  End Sub)
        For Each r As Rectangle In bounds
            For y As Integer = r.Top To r.Bottom
                If y > yupper Then Exit For
                For x As Integer = r.Left To r.Right
                    If x > xupper Then Exit For
                    If x = r.Left Then
                        If y = r.Top Then
                            Select Case _Cells(x, y)
                                Case FrameCellType.Empty
                                    _Cells(x, y) = FrameCellType.TopLeft
                                    updateBuffer(x, y, TopLeft)
                                Case FrameCellType.Horizontal
                                    _Cells(x, y) = FrameCellType.TeeTop
                                    updateBuffer(x, y, TeeTop)
                                Case FrameCellType.Vertical, FrameCellType.BottomLeft
                                    _Cells(x, y) = FrameCellType.TeeLeft
                                    updateBuffer(x, y, TeeLeft)
                                Case FrameCellType.TopRight
                                    _Cells(x, y) = FrameCellType.TeeTop
                                    updateBuffer(x, y, TeeTop)
                                Case FrameCellType.BottomRight, FrameCellType.TeeRight, FrameCellType.TeeBottom
                                    _Cells(x, y) = FrameCellType.Cross
                                    updateBuffer(x, y, Cross)
                            End Select
                        ElseIf y = r.Bottom Then
                            Select Case _Cells(x, y)
                                Case FrameCellType.Empty
                                    _Cells(x, y) = FrameCellType.BottomLeft
                                    updateBuffer(x, y, BottomLeft)
                                Case FrameCellType.Horizontal, FrameCellType.BottomRight
                                    _Cells(x, y) = FrameCellType.TeeBottom
                                    updateBuffer(x, y, TeeBottom)
                                Case FrameCellType.Vertical, FrameCellType.TopLeft
                                    _Cells(x, y) = FrameCellType.TeeLeft
                                    updateBuffer(x, y, TeeLeft)
                                Case FrameCellType.TopRight, FrameCellType.TeeRight, FrameCellType.TeeTop
                                    _Cells(x, y) = FrameCellType.Cross
                                    updateBuffer(x, y, Cross)
                            End Select
                        Else
                            Select Case _Cells(x, y)
                                Case FrameCellType.Empty
                                    _Cells(x, y) = FrameCellType.Vertical
                                    updateBuffer(x, y, Vertical)
                                Case FrameCellType.Horizontal, FrameCellType.TeeTop, FrameCellType.TeeBottom
                                    _Cells(x, y) = FrameCellType.Cross
                                    updateBuffer(x, y, Cross)
                                Case FrameCellType.TopLeft, FrameCellType.BottomLeft
                                    _Cells(x, y) = FrameCellType.TeeLeft
                                    updateBuffer(x, y, TeeLeft)
                                Case FrameCellType.TopRight, FrameCellType.BottomRight
                                    _Cells(x, y) = FrameCellType.TeeRight
                                    updateBuffer(x, y, TeeRight)
                            End Select
                        End If
                    ElseIf x = r.Right Then
                        If y = r.Top Then
                            Select Case _Cells(x, y)
                                Case FrameCellType.Empty
                                    _Cells(x, y) = FrameCellType.TopRight
                                    updateBuffer(x, y, TopRight)
                                Case FrameCellType.Horizontal
                                    _Cells(x, y) = FrameCellType.TeeTop
                                    updateBuffer(x, y, TeeTop)
                                Case FrameCellType.Vertical, FrameCellType.BottomRight
                                    _Cells(x, y) = FrameCellType.TeeRight
                                    updateBuffer(x, y, TeeRight)
                                Case FrameCellType.TopLeft
                                    _Cells(x, y) = FrameCellType.TeeTop
                                    updateBuffer(x, y, TeeTop)
                                Case FrameCellType.BottomLeft, FrameCellType.TeeLeft, FrameCellType.TeeBottom
                                    _Cells(x, y) = FrameCellType.Cross
                                    updateBuffer(x, y, Cross)
                            End Select
                        ElseIf y = r.Bottom Then
                            Select Case _Cells(x, y)
                                Case FrameCellType.Empty
                                    _Cells(x, y) = FrameCellType.BottomRight
                                    updateBuffer(x, y, BottomRight)
                                Case FrameCellType.Horizontal, FrameCellType.BottomLeft
                                    _Cells(x, y) = FrameCellType.TeeBottom
                                    updateBuffer(x, y, TeeBottom)
                                Case FrameCellType.Vertical, FrameCellType.TopRight
                                    _Cells(x, y) = FrameCellType.TeeRight
                                    updateBuffer(x, y, TeeRight)
                                Case FrameCellType.TopLeft, FrameCellType.TeeLeft, FrameCellType.TeeTop
                                    _Cells(x, y) = FrameCellType.Cross
                                    updateBuffer(x, y, Cross)
                            End Select
                        Else
                            Select Case _Cells(x, y)
                                Case FrameCellType.Empty
                                    _Cells(x, y) = FrameCellType.Vertical
                                    updateBuffer(x, y, Vertical)
                                Case FrameCellType.Horizontal, FrameCellType.TeeTop, FrameCellType.TeeBottom
                                    _Cells(x, y) = FrameCellType.Cross
                                    updateBuffer(x, y, Cross)
                                Case FrameCellType.TopLeft, FrameCellType.BottomLeft
                                    _Cells(x, y) = FrameCellType.TeeLeft
                                    updateBuffer(x, y, TeeLeft)
                                Case FrameCellType.TopRight, FrameCellType.BottomRight
                                    _Cells(x, y) = FrameCellType.TeeRight
                                    updateBuffer(x, y, TeeRight)
                            End Select
                        End If
                    Else
                        If y = r.Top Then
                            Select Case _Cells(x, y)
                                Case FrameCellType.Empty
                                    _Cells(x, y) = FrameCellType.Horizontal
                                    updateBuffer(x, y, Horizontal)
                                Case FrameCellType.Vertical, FrameCellType.TeeLeft, FrameCellType.TeeRight
                                    _Cells(x, y) = FrameCellType.Cross
                                    updateBuffer(x, y, Cross)
                                Case FrameCellType.TopLeft, FrameCellType.TopRight
                                    _Cells(x, y) = FrameCellType.TeeTop
                                    updateBuffer(x, y, TeeTop)
                                Case FrameCellType.BottomLeft, FrameCellType.BottomRight
                                    _Cells(x, y) = FrameCellType.TeeBottom
                                    updateBuffer(x, y, TeeBottom)
                            End Select
                        ElseIf y = r.Bottom Then
                            Select Case _Cells(x, y)
                                Case FrameCellType.Empty
                                    _Cells(x, y) = FrameCellType.Horizontal
                                    updateBuffer(x, y, Horizontal)
                                Case FrameCellType.Vertical, FrameCellType.TeeLeft, FrameCellType.TeeRight
                                    _Cells(x, y) = FrameCellType.Cross
                                    updateBuffer(x, y, Cross)
                                Case FrameCellType.TopLeft, FrameCellType.TopRight
                                    _Cells(x, y) = FrameCellType.TeeTop
                                    updateBuffer(x, y, TeeTop)
                                Case FrameCellType.BottomLeft, FrameCellType.BottomRight
                                    _Cells(x, y) = FrameCellType.TeeBottom
                                    updateBuffer(x, y, TeeBottom)
                            End Select
                        End If
                    End If
                Next
            Next
        Next
    End Sub

    ''' <summary>
    ''' Sets the frame characters to the specified characters. Must be exactly 11 characters in the order of:
    ''' bottom left, bottom right, cross, bottom, bottom T, left intersection, right intersection, top T,
    ''' top left, top right, side.
    ''' </summary>
    ''' <param name="characters"></param>
    Public Shared Sub SetCharacters(characters As String)
        If characters.Length = 11 Then
            _Characters = characters
        Else
            Throw New ArgumentException("Must supply exactly eleven characters.")
        End If
    End Sub

    ''' <summary>
    ''' Sets the frame characters to double bar ASCII lines "╚╝╬═╩╠╣╦╔╗║"
    ''' </summary>
    Public Shared Sub SetDoubleBar()
        _Characters = "╚╝╬═╩╠╣╦╔╗║"
    End Sub

    ''' <summary>
    ''' Sets the frame characters to single bar ASCII lines "└┘┼─┴├┤┬┌┐│"
    ''' </summary>
    Public Shared Sub SetSingleBar()
        _Characters = "└┘┼─┴├┤┬┌┐│"
    End Sub
End Class

Public Enum FrameCellType
    Empty
    Horizontal
    Vertical
    BottomLeft
    BottomRight
    TopLeft
    TopRight
    TeeBottom
    TeeLeft
    TeeRight
    TeeTop
    Cross
End Enum

Public Class FrameCellTypeCollection
    Private _listcore(,) As FrameCellType


End Class